package com.suneast.suneaststore.util.net.interceptors;

import android.support.annotation.NonNull;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.suneast.suneaststore.API;
import com.suneast.suneaststore.app.AccountManager;
import com.suneast.suneaststore.modules.main.event.SignOutDateEvent;
import com.suneast.suneaststore.util.log.LatteLogger;
import com.suneast.suneaststore.util.net.RestClient;

import org.greenrobot.eventbus.EventBus;

import java.io.IOException;

import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okio.Buffer;

public class TokenInterceptor extends BaseInterceptor {
    private final static String TAG = TokenInterceptor.class.getSimpleName();

    private static long last = -1;

    private final static long CHECK_DURATION = 60 * 1000 * 30;

    @Override
    public Response intercept(@NonNull Chain chain) throws IOException {
        Request request = chain.request();
//        DebugPrint("old", request);
        if (refreshToken(request)) {
            android.util.Log.d(TAG, "token refreshed by: " + request.toString());
            RequestBody requestBody = request.body();
            if (requestBody != null) { // 一般不为空，因为只有需要token的请求才会有token过期的错误
                String postString = bodyToString(requestBody);
                StringBuilder builder = new StringBuilder(postString);
                int start, end;
                if (excludeAPIs(request.url().toString(), API.PIC_UPLOAD, API.UPDATE_HEAD_IMG)) {
                    start = builder.indexOf("token=") + "token=".length();
                    end = builder.indexOf("&", start);
                    if (end == -1) { // token在最后一个字段
                        end = builder.length();
                    }
                } else {
                    start = builder.indexOf("\r\n\r\n", builder.indexOf("Content-Length", builder.indexOf("\"token\""))) + "\r\n\r\n".length();
                    end = builder.indexOf("\r\n", start);
                }
                builder.replace(start, end, AccountManager.getToken());
                Request newRequest = request.newBuilder().post(RequestBody.create(requestBody.contentType(), builder.toString())).build();
                DebugPrint("new", newRequest);
                return chain.proceed(newRequest);
            }
        }
        return chain.proceed(request);
    }

    private void DebugPrint(String mark, Request request) {
        android.util.Log.d(TAG, mark + " request: " + request.toString());
        RequestBody body = request.body();
        if (body != null) {
            android.util.Log.d(TAG, mark + " request body: " + bodyToString(body));
        }
    }

    /**
     * 验证token是否过期
     *
     * @param request 请求
     * @return true 过期， false 没过
     */
    private static boolean refreshToken(Request request) {
        if (!AccountManager.getToken().isEmpty() && excludeAPIs(request.url().toString(), API.REFRESH_TOKEN, API.CHECK_TOKEN) && filterTime()) {
            retrofit2.Response<String> response = RestClient.builder()
                    .url(API.CHECK_TOKEN)
                    .params("token", AccountManager.getToken())
                    .params("sign", AccountManager.getSignFromLocal())
                    .build()
                    .postSync();
            if (response != null && response.code() == 200) {
                JSONObject resp = JSON.parseObject(response.body());
                LatteLogger.json(TAG, response.body());
                if (resp != null) {
                    switch (resp.getIntValue("code")) {
                        case 1:
                            String newToken = resp.getJSONObject("data").getString("token");
                            android.util.Log.d(TAG, "refresh token " + newToken);
                            if (newToken != null && !newToken.isEmpty()) {
                                AccountManager.setTokenToLocal(newToken);
                                return bodyToString(request.body()).contains("token");  // 不带token的请求不用管
                            }
                            break;
                        case 1003:
                            EventBus.getDefault().post(new SignOutDateEvent()); // 最后返回false, 因为已经不是token过期了，
                            break;
                        case 0: // 0 不需要刷新
                        default: // 其他情况有吗？
                            break;
                    }
                }
            } else {
                android.util.Log.e(TAG, "refresh Token while server response: " + (response == null ? "nothing" : response.code()));
            }
        }
        return false;
    }

    /**
     * 检查request是不包含后面的api请求
     *
     * @param apis api请求
     * @return true不包含后面的api, false包含
     */
    private static boolean excludeAPIs(String urlString, String... apis) {
        for (String api : apis) {
            if (urlString.contains(api)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 时间过滤
     * @return true，可执行 false，被过滤
     */
    private static boolean filterTime() {
        boolean result = System.currentTimeMillis() - last > CHECK_DURATION;
        last = System.currentTimeMillis();
        return result;
    }

    private static String bodyToString(final RequestBody body) {
        try {
            final Buffer buffer = new Buffer();
            if (body == null) {
                return "";
            }
            body.writeTo(buffer);
            return buffer.readUtf8();
        } catch (final IOException e) {
            e.printStackTrace();
            return "";
        }
    }
}
